ERROR HANDLING

throw("yooooo");

throws are destroyer of worlds but not destroyers of pointers to worlds - in other words, all the shit made before the throw will have their destructors called, but if you used new or something and your variable is a pointer to an object instead of the object itself, well, yeah.

If you made something like Str * str = new Str();, the contents of str would not be freed. However, the contents of str = Str(); would be freed.

Also, destructors will be called in the reverse order of initialization.


abort() is used to exit out of a program.



int main(void)
{
  . . .
  
  try
  {
    // code that might cause an exception (throw) and needs
    // to be protected
  }
  catch (const char *p) // catch a const char pointer
  {
    // code that will handle the char pointer exception from
    // the try block above
  }
  catch (int i) // catch an integer
  {
    // code that will handle the integer exception from
    // the try block above
  }
  catch (exception e) // catch an "exception" object
  {
    // code that will handle the "exception" object from
    // the try block above
  }
  
  . . .
  
}

If an exception is not caught, it will end up calling the abort() method and terminating the program.


You can "tag" a function with an exception specification, but it is not foolproof as you can still throw other exceptions.

  double QRoot(double a, double b, double c) throw(const char *, double)

From additional research I have found that this is mostly bad because it not only shits all over performance (it forces the run-time to check for unexpected exceptions) it is also weakly enforced, and doesn't make the code safer.

It's even in the high integerity C++ coding standard to NOT use throw exception specifications as they have been deprecated in C++11. So it probably won't come out for the exam.

You can also not put anything in the throw parameters (throw()), and this will make the program not compile code for any potential exceptions. However, any exceptions thrown will not, as I said above, prevent the program from compiling. However, it will probably mess up real bad.

http://www.codingstandard.com/rule/1-3-5-do-not-use-throw-exception-specifications/


Use try and catch individually with each statement that may throw an exception. This is because if several functions that may throw exceptions are put into the "try" section, then only the first exception will be caught.


abort() exits your program without calling functions registered using atexit() first, and without calling objects' destructors first. exit() does both before exiting your program. It does not call destructors for automatic objects though.

A a;
void test() { 
    static A b;
    A c;
    exit(0);
}

abort() would call none of the destructors, exit() will call only a and b's destructors, but not c's.


Classes with data about what kinda exception and other shit can be thrown as well. These are called Exception Classes.


It is common for exception classes to derive from well, THE exception class (in this case, the BASE exception class in the STL).

The following class is std::exception

class exception 
{
  public:
    exception() throw();
    exception(const exception& rhs) throw();
    exception& operator=(const exception& rhs) throw();
    virtual ~exception() throw();
    virtual const char *what() const throw();
};

Here's an example of a custom Exception Class.

class SubscriptError : public std::exception
{
  private:
    int subscript_;

  public:
    SubscriptError(int Subscript) : subscript_(Subscript) {};
    int GetSubscript(void) const { return subscript_; }
    virtual const char *what(void) const throw();
    {
      static char buff[80];
      sprintf(buff, "Subscript error at index: %d", subscript_);
      return buff;
    }
};

NOT COVERED IN NOTES BUT COVERED IN CLASS

The noexcept specifier was covered by Prasanna but for some reason isn't in the notes. It's probably good to know anyway.

noexcept is an improved version of throw(), which is deprecated in C++11. Unlike throw(), noexcept will not call std::unexpected and may or may not unwind the stack, which potentially allows the compiler to implement noexcept without the runtime overhead of throw().

It's also an operator, but that isn't quite as important.


SUMMARY

Keywords to remember: throw, try, catch.

Exception class has two virtual functions, what(), which takes in nothing and returns a pointer to a constant char (basically, a C-style string) and the destructor.

When modifying what in a derived exception class, do this:

  sprintf(buff, "Subscript error at index: %d", subscript_);